package dm.ast.model.gen.factory;

import test.utility.Randomly;

import java.util.ArrayList;
import java.util.List;

/**
 * @author scy
 * @date 2024/4/16
 */
public class CaseExpModelFactory extends BaseModelFactory {

    //至少划分成minField个模板
    public static ComplexityModel caseExpModels(int wid_t, int dep_t, int minField) {
        List<ComplexityModel> models = new ArrayList<ComplexityModel>();

        //1、极值分配,权重为1
        models.addAll(modelExtreme(wid_t, dep_t, minField));

        //2、深度平均分配，权重为5

        models.addAll(modelAverage(wid_t, dep_t, minField));

        if (models.isEmpty()) {
            throw new AssertionError();
        }

        return getRanComplexityModel(models);
    }

    //极值分配
    public static List<ComplexityModel> modelExtreme(int wid_t, int dep_t, int minField) {
        List<ComplexityModel> extreme = new ArrayList<ComplexityModel>();
        //最多分支
        int maxCount = FactoryConstant.MAX_CASE_WHEN * 2 + 1;
        if (maxCount > wid_t) {
            maxCount = wid_t;
        }
        ComplexityModel maxWhen = new ComplexityModel(maxCount);
        for (int i = 0; i < maxWhen.count; i++) {
            maxWhen.comps[i].wid_t = 1;
            maxWhen.comps[i].dep_t = 1;
        }

        int j = Randomly.getInteger(0, maxWhen.count);
        maxWhen.comps[j].dep_t = dep_t;
        maxWhen.comps[j].wid_t = wid_t - maxWhen.count + 1;
        if (maxWhen.comps[j].wid_t < 1) {
            maxWhen.comps[j].wid_t = 1;
        }
        extreme.add(maxWhen);
        //最小分支
        int minCount = minField * 2 + 1;
        if (minCount > wid_t) {
            minCount = wid_t;
        }
        ComplexityModel minWhen = new ComplexityModel(minCount);
        for (int i = 0; i < minWhen.count; i++) {
            minWhen.comps[i].wid_t = 1;
            minWhen.comps[i].dep_t = 1;
        }
        j = Randomly.getInteger(0, minWhen.count);
        minWhen.comps[j].dep_t = dep_t;
        minWhen.comps[j].wid_t = wid_t - minWhen.count + 1;
        if (minWhen.comps[j].wid_t < 1) {
            minWhen.comps[j].wid_t = 1;
        }
        extreme.add(minWhen);
        return extreme;
    }

    //深度平均分配
    public static List<ComplexityModel> modelAverage(int wid_t, int dep_t , int minField) {
        List<ComplexityModel> average = new ArrayList<ComplexityModel>();
        int count = Randomly.getInteger(minField , FactoryConstant.MAX_CASE_WHEN * 2 + 1);

        ComplexityModel model = new ComplexityModel(count);
        //先把一个深度设为dep_t，剩余的随机
        int maxWid = setExpWidtByDept(dep_t);
        int tmpWid = wid_t - maxWid;
        int j = Randomly.getInteger(0, model.count);
        model.comps[j].dep_t = dep_t;
        model.comps[j].wid_t = maxWid;
        for (int i = 0; i < model.count; i++) {
            if(i == j){
                continue;
            }
            int tmp = dep_t;
            do { //先随机深度
                model.comps[i].dep_t = Randomly.getInteger(1, tmp + 1);
                model.comps[i].wid_t = setExpWidtByDept(model.comps[i].dep_t);
                //若导致宽度太大，暂时减小深度
                if(model.comps[i].wid_t > tmpWid / (count - 1) && model.comps[i].dep_t > 1){
                    tmp--;
                }else {
                    break;
                }
            }while (tmp > 1);

            if(model.comps[i].wid_t > tmpWid / (count - 1)){
                model.comps[i].wid_t = tmpWid / (count - 1) > 0 ? tmpWid / (count - 1) : 1;
            }

        }
        model.weight = 5;
        average.add(model);

        return average;
    }
}
